#!/usr/bin/python2.4
# jhebert@cs.washington.edu

import time
import threading
import Queue
import workerThread



class WorkerPool:
  """ Class to hold information for a set of workerThreads.
  Still need to solve the problem of when the threads are done working. """

  def __init__(self, numOfThreads):
    """ Create as many threads as possible up to the number
    that was requested. I'm not sure how many can actually be
    created ususally, but 100 works and 1000 doesn't. """
    self.logging = Queue.Queue()
    self.freeQueue = Queue.Queue()
    # A queue of jobs that need workers.
    self.jobQueue = Queue.Queue()
    # An array of workerThread objects.
    self.workers = []
    for i in range(numOfThreads):
      try:
        w = workerThread.WorkerThread(self)
        t = threading.Thread(target = w.Run)
        w.SetThread(t)
        self.workers.append(w)
        self.freeQueue.put(w)
        t.start()
      except:
        continue

  def RefreshWorkerPool(self):
    """ Iterate through the workers and create threads for
    those that are not alive."""
    for worker in self.workers:
      if(not(worker.thread.isAlive())):
        t = threading.Thread(target = w.Run)
        t.start()

  def StartWorkerJob(self, name, prog):
    """ Add a job to the pool. If there is a free worker, immediately
    assign it to the job, otherwise put the job on the job queue."""
    try:
      w = self.freeQueue.get(False)
      w.AddToQueue(name, prog)
    except:
      self.jobQueue.put((name, prog))

  def ReturnWorker(self, worker):
    """ Called by a returning worker. If there is a free job,
    then keep the worker working. Otherwise put the worker
    on the free queue. """
    try:
      j = self.jobQueue.get(False)
      name, prog = j
      worker.AddToQueue(name, prog)
    except:
      self.freeQueue.put(worker)

  def Stop(self):
    """ Sleep until no threads are working and the jobQueue is empty.
    Then tell each worker to stop working. Maybe I should also join
    all of the threads? """
    time.sleep(.5)
    while(not(self.jobQueue.empty())):
      time.sleep(.5)
    for w in self.workers:
      w.Stop()

  def StopNow(self):
    """ If we want to stop NOW and not gracefully - tell all
    workers they should stop. Is there a more forceful thread
    kill sort of method that could be used? """
    for w in self.workers:
      w.Stop()
